#pragma once
#include <iostream>
#include <memory>
#include <sys/types.h>
#include <sys/socket.h>
#include "Connection.hpp"
#include "Protocol.hpp"
#include "Calculate.hpp"
static int g_buffersize = 1024;

using namespace Protocol;

class HandlerConnection
{
public:
    static void HandlerRecver(Connection *conn)
    {
        std::string &inbuff = conn->GetInbuffer();
        std::unique_ptr<Factory> factory = std::make_unique<Factory>();
        auto req = factory->BuildRequest();
        std::string message;
        Calculate calculate;
        while (Protocol::Decode(inbuff, &message))
        {
            // 走到这里说明是一个完整的报文，缓冲区的数据被上层拿走了!
            // 1.解包成功
            // 2.开始反序列化
            if (!req->DeSerialize(message))
            {

                lg.LogMessage(Warning, "DeSerialize error");
                continue;
            }
            // 3.业务处理
            auto resp = calculate.Cal(req);
            std::string send_str;
            // 4.结果序列化并添加报头
            resp->Serialize(&send_str);
            send_str = Encode(send_str);

            // 5.添加进发送缓冲区
            conn->AddOutbuffer(send_str);
        }
        // 统一处理发
        if (!conn->IsOutbufferEmpty())
        {
            conn->_sender(conn);
        }
    }

    // 负责一直读取，尝试分析发送
    static void Recver(Connection *conn)
    {
        errno = 0;
        char inbuffer[g_buffersize];
        while (true)
        {
            int n = ::recv(conn->GetConnFd(), inbuffer, sizeof(inbuffer) - 1, 0);
            if (n > 0)
            {
                // 读取成功一个数据
                inbuffer[n] = 0;
                conn->AddInbuffer(inbuffer);
            }
            else
            {
                // 异常情况
                // 没读到数据
                if (errno == EAGAIN)
                    break;
                else if (errno == EINTR)
                    continue;
                // 读到异常
                else
                {
                    
                    conn->_excepter(conn);
                    return;
                }
            }
        }
        // 尝试分析报文
        std::cout << "sockfd# " << conn->GetConnFd() << " say:" << std::endl
                  << conn->GetInbuffer() << std::endl;
        HandlerRecver(conn);
    }

    // 正常读，除非读异常才不读（发送缓冲区被写满），需要特殊处理
    static void Sender(Connection *conn)
    {
        errno = 0;
        std::string &outbuffer = conn->GetOutbuffer();
        while (true)
        {
            int n = ::send(conn->GetConnFd(), outbuffer.c_str(), outbuffer.size(), 0);
            if (n >= 0)
            {
                // 发送正常
                outbuffer.erase(0, n);
                if (outbuffer.empty())
                    break;
            }
            else
            {
                // 处理异常
                if (errno == EAGAIN)
                    break; // 缓冲区别写满了，出错
                else if (errno == EINTR)
                    continue;
                else
                {
                    // 调用异常事件
                    
                    conn->_excepter(conn);
                    return;
                }
            }
        }

        if (!conn->IsOutbufferEmpty())
        {
            // 关闭关心事件
            conn->_R->EventEnable(conn->GetConnFd(), true, true);
        }
        else
        {
            // 需要下一次关心
            conn->_R->EventEnable(conn->GetConnFd(), true, false);
        }
    }

    static void Excepter(Connection *conn)
    {

        std::cout<<"fd#"<<conn->GetConnFd()<< " quit"<<std::endl;
        // 取消关心
        // 取消链接
        conn->SetEvent(0);
        conn->_R->RemoveConnection(conn->GetConnFd());

        // delete conn
        // close fd
        close(conn->GetConnFd());
        delete conn;
    }

private:
};